﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MoonLight.LibCommon;
using PVAutoTest.LibCommon;
using PVAutoTest.BizSimulator;

namespace PVAutoTest.TestMngr
{
    public class TestCase : Notifier
    {
        public TestCase(Notifier parent)
        {
            m_event = new TestData_Event();
            m_check_point = new TestCheckPoint();
            m_result = new TestCaseResult();
            m_sim = new Simulator(this);
            m_enable = false;
            m_parent = parent;
            m_e = new TestCaseResultEventArgs();
        }

        ~TestCase()
        {
        }

        public void Init(TestData_Event t_event, int cp_mask)
        {
            m_event.case_no = t_event.case_no;
            m_event.case_sub_no = t_event.case_sub_no;
            m_event.msg_no = t_event.msg_no;
            m_event.dev_id = t_event.dev_id;
            m_event.set_state = t_event.set_state;
            m_event.component_id = t_event.component_id;
            m_event.component_state = t_event.component_state;
            m_event.event_no = t_event.event_no;
            m_event.msg_str = t_event.msg_str;
            m_event.event_id = t_event.event_id;

            m_check_point.SetCheckPoints(cp_mask);
            m_check_point.SetExpectedResult(m_event);
        }

        public int GetCheckPoints()
        {
            return m_check_point.GetCheckPoints();
        }

        public void SetCheckPoints(int cp_mask)
        {
            m_check_point.SetCheckPoints(cp_mask);
        }

        public CheckPoint_DB GetDBCheckPoints()
        {
            return m_check_point.GetDBCheckPoints();
        }

        public void SetDBCheckPoints(CheckPoint_DB cp_db)
        {
            m_check_point.SetDBCheckPoints(cp_db);
        }

        public bool IsEnable()
        {
            return m_enable;
        }

        public void Enable()
        {
            m_enable = true;
        }

        public void Disable()
        {
            m_enable = false;
        }

        public void RunCase()
        {
            if ((m_check_point.GetCheckPoints() & (int)ProjectDefine.TCCheckPoints_e.CP_UNKNOWN) == 1)
            {
                Logger.WriteLog("Case[" + m_event.case_no + "] has no check point set, just igore the case");
                m_result.TestResult = ProjectDefine.TCResult_e.TC_UNKNOWN;
                return;
            }

            m_result.start_time = DateTime.Now;
            test_method();
            return;
        }

        public TestCaseResult GetResult()
        {
            return m_result;
        }

        public TestData_Event GetEvent()
        {
            return m_event;
        }

        public override void handle_message(MessageInfo msg)
        {
            switch ((ProjectDefine.MsgType_e)msg.msg_type)
            {
                case ProjectDefine.MsgType_e.MSG_EVENT_FINISHED:
                    {
                        MessageInfo ts_msg = new MessageInfo(ProjectDefine.MsgType_e.MSG_CASE_FINISHED);
                        if ((m_check_point.GetCheckPoints() & (int)ProjectDefine.TCCheckPoints_e.CP_UNKNOWN) == 1)
                        {
                            m_result.end_time = DateTime.Now;
                            Logger.WriteLog("Case[" + m_event.case_no + "] no check point");
                            m_result.TestResult = ProjectDefine.TCResult_e.TC_UNKNOWN;
                            ts_msg = new MessageInfo(ProjectDefine.MsgType_e.MSG_CASE_FINISHED);
                            m_parent.handle_message(ts_msg);
                            return;
                        }

                        if ((m_check_point.GetCheckPoints() & (int)ProjectDefine.TCCheckPoints_e.CP_DATABASE) == 1)
                        {
                            string err_info = "";
                            string expect_value = "";
                            string actual_value = "";
                            m_result.Info = "";
                            m_result.expect_result = "";
                            m_result.actual_result = "";
                            m_result.TestResult = m_check_point.CheckPointDB(ref err_info, ref expect_value, ref actual_value);
                            if (m_result.TestResult != ProjectDefine.TCResult_e.TC_PASSED)
                            {
                                m_result.end_time = DateTime.Now;
                                m_result.Info = err_info;
                                m_result.expect_result = expect_value;
                                m_result.actual_result = actual_value;
                                Logger.WriteLog("Case[" + m_event.case_no + "] failed at check point in DB");
                                m_e.SetTestResult(m_event.case_no, m_event.case_sub_no, m_result);
                                if (OnChange != null)
                                    OnChange(this, m_e);
                                ts_msg = new MessageInfo(ProjectDefine.MsgType_e.MSG_CASE_FINISHED);
                                m_parent.handle_message(ts_msg);
                                return;
                            }
                        }

                        if ((m_check_point.GetCheckPoints() & (int)ProjectDefine.TCCheckPoints_e.CP_TRACE) == 1)
                        {
                            m_result.TestResult = m_check_point.CheckPointTrace();
                            if (m_result.TestResult != ProjectDefine.TCResult_e.TC_PASSED)
                            {
                                m_result.end_time = DateTime.Now;
                                Logger.WriteLog("Case[" + m_event.case_no + "] failed at check point in TRACE");
                                m_e.SetTestResult(m_event.case_no, m_event.case_sub_no, m_result);
                                ts_msg = new MessageInfo(ProjectDefine.MsgType_e.MSG_CASE_FINISHED);
                                m_parent.handle_message(ts_msg);
                                return;
                            }
                        }

                        if ((m_check_point.GetCheckPoints() & (int)ProjectDefine.TCCheckPoints_e.CP_LOG) == 1)
                        {
                            m_result.TestResult = m_check_point.CheckPointLog();
                            if (m_result.TestResult != ProjectDefine.TCResult_e.TC_PASSED)
                            {
                                m_result.end_time = DateTime.Now;
                                Logger.WriteLog("Case[" + m_event.case_no + "] failed at check point in LOG");
                                m_e.SetTestResult(m_event.case_no, m_event.case_sub_no, m_result);
                                ts_msg = new MessageInfo(ProjectDefine.MsgType_e.MSG_CASE_FINISHED);
                                m_parent.handle_message(ts_msg);
                                return;
                            }
                        }
                        m_result.end_time = DateTime.Now;
                        Logger.WriteLog("Case[" + m_event.case_no + "] passed");
                        m_result.TestResult = ProjectDefine.TCResult_e.TC_PASSED;
                        m_e.SetTestResult(m_event.case_no, m_event.case_sub_no, m_result);
                        if (OnChange != null)
                            OnChange(this, m_e);
                        ts_msg = new MessageInfo(ProjectDefine.MsgType_e.MSG_CASE_FINISHED);
                        m_parent.handle_message(ts_msg);
                    }
                    break;
                default:
                    {
                        Logger.WriteLog("unknown msg type [" + msg.msg_type.ToString() + "]");
                        MessageInfo ts_msg = new MessageInfo(ProjectDefine.MsgType_e.MSG_CASE_FINISHED);
                        m_parent.handle_message(ts_msg);
                    }
                    break;
            }
        }

        private void test_method()
        {
            //sim will raise a msg back when interaction is finished
            m_sim.SetTestData(m_event.dev_id, m_event.event_no, m_event.event_id, m_event.msg_str);
            m_sim.SendEvent();
        }

        private bool m_enable;
        private TestData_Event m_event;
        private TestCaseResult m_result;
        private TestCheckPoint m_check_point;
        private Simulator m_sim;

        public delegate void Delegate_TestCaseResult(object sender, TestCaseResultEventArgs e);
        public event Delegate_TestCaseResult OnChange;
        private TestCaseResultEventArgs m_e;
        private Notifier m_parent;
    }

    public class TestCaseResultEventArgs : EventArgs
    {
        public TestCaseResultEventArgs()
        {
            m_result = new TestCaseResult();
        }

        public void SetTestResult(int id, int subno, TestCaseResult result)
        {
            m_result = result;
            m_case_id = id;
            m_case_sub_no = subno;
        }

        public TestCaseResult GetTestResult()
        {
            return m_result;
        }

        public int GetCaseId()
        {
            return m_case_id;
        }

        public int GetCaseSubNo()
        {
            return m_case_sub_no;
        }

        private TestCaseResult m_result;
        private int m_case_id;
        private int m_case_sub_no;
    }
}
